/*
 * @Author: YTian
 * @Date: 2023-05-14 13:30:22
 * @LastEditTime: 2023-05-18 10:02:06
 * @Description:
 * @FilePath: \pcsong\src\global\data.ts
 */
// ========= 导入vue api ========= //
import { reactive, nextTick, ref, watch, computed, toRef } from 'vue'
import type { Ref } from 'vue'

// ========= 导入api 数据 ========= //
import { link_get, deal__with } from './api'
import type { Song } from './api'

// ========= 数据持久化 ========= //

/**
 * @description: 添加值
 * @param {string} name: 名称
 * @param {string} value: 对应的值, 需要是字符串
 * @return {*}
 */
const lasting_add = (name: string, value: string): void => {
	localStorage.setItem(name, value)
}

/**
 * @description: 取出值
 * @param {string} name: 取出值的名称
 * @param {T} def: 默认值, 如果没有找到该名称的值就使用def
 * @return {*}
 */
const lasting_get = <T>(name: string, def?: T): T =>
	localStorage.getItem(name)
		? JSON.parse(localStorage.getItem(name) as string)
		: def ?? null

// ========= 音乐数据 ========= //
const Song__datas = reactive<{ index: number; links: Song[] }>({
	// & 序号, -1 代表现在列表里一首歌都没有
	index: lasting_get<number>('index', -1),

	// & 存放的音乐
	links: lasting_get<Song[]>('links', [])
})

const song__index_get = (): Ref<number> => toRef(Song__datas, 'index')

/**
 * @description: 获取当前播放的歌曲的数据
 * @param {*} Ref
 * @return {*}
 */
const current__data = computed<Song | 'no'>(() => {
	return Song__datas.index !== -1
		? Song__datas.links[Song__datas.index]
		: 'no'
})

const song__data_links_get = (): Song[] => Song__datas.links

/**
 * @description: 根据传递的数据填加歌曲到播放列表
 * @param {Song} data
 * @return {*}
 */
const Song__datas__links_push = (data: Song | Song[]): void => {
	// & 如果是数组
	if (Array.isArray(data)) {
		Song__datas.links.splice(Song__datas.index + 1, 0, ...data)
	} else {
		Song__datas.links.splice(Song__datas.index + 1, 0, data)
	}

	lasting_add('links', JSON.stringify(Song__datas.links))

	if (Song__datas.index === -1) {
		specify__index(0)
	}
}

/**
 * 在删除当前播放歌曲的时候先切换到上一曲再删除
 * 在只有列表里只有一首歌的时候会把index变成-1代表列表内无歌曲
 *
 * @description: 根据传递的index删除对应歌曲
 * @param {number} index
 * @return {*}
 */
const Song__datas__links_del = (index: number): void => {
	if (Song__datas.links.length === 1) {
		specify__index(-1)
	}

	if (index <= Song__datas.index) {
		audio__load()
	}

	// & 根据index删除数组内容
	Song__datas.links.splice(index, 1)

	lasting_add('links', JSON.stringify(Song__datas.links))
}

/**
 * @description: 删除列表内所有歌曲
 * @param {*} void
 * @return {*}
 */
const Song__datas__links_all_del = (): void => {
	specify__index(-1)
	Song__datas.links.splice(0)
	lasting_add('links', JSON.stringify(Song__datas.links))
}

export {
	song__index_get,
	song__data_links_get,
	current__data,
	Song__datas__links_push,
	Song__datas__links_del,
	Song__datas__links_all_del
}

// ========= dom操作部分 ========= //
let audio_src = Song__datas.links[Song__datas.index]?.id
	? await link_get(Song__datas.links[Song__datas.index].id)
	: ''

const audio = document.createElement('audio')
audio.src = audio_src

document.body.appendChild(audio)

// & pause代表未播放, play代表已经播放
let audio__state = ref<'pause' | 'play'>('pause')

/**
 * @description: 根据传递进来的值来决定进行什么操作, 不传就默认反转
 * @param {*} par
 * @return {*}
 */
const audio__pause_or_play = (par?: 'pause' | 'play'): void => {
	if (!par) {
		par = audio__state.value === 'play' ? 'pause' : 'play'
	}

	if (par === 'pause') {
		audio.pause()
		audio__state.value = 'pause'

		return
	}

	if (par === 'play') {
		audio.play()
		audio__state.value = 'play'

		return
	}
}

/**
 * @description: 上一曲或者下一曲 默认下一曲
 * @param {*} par
 * @return {*}
 */
const last_or_next = (par: 'last' | 'next' = 'next'): void => {
	const length = Song__datas.links.length

	if (par === 'last') {
		// & 上一曲
		Song__datas.index =
			Song__datas.index - 1 < 0 ? length - 1 : Song__datas.index - 1
	} else {
		// & 下一曲
		Song__datas.index =
			Song__datas.index + 1 === length ? 0 : Song__datas.index + 1
	}
}

/**
 * @description: 指定播放哪一曲
 * @param {number} index
 * @return {*}
 */
const specify__index = (index: number): void => {
	Song__datas.index = index
}

const audio__load = async (): Promise<void> => {
	audio__pause_or_play('pause')
	audio_nature.time = 0

	const id: string = Song__datas.links[Song__datas.index + 1].id

	const new__src: string = await link_get(id)

	if (audio.src !== new__src) {
		audio.src = new__src
	}

	audio_nature.max = audio.duration

	nextTick((): void => {
		audio__pause_or_play('play')
	})
}

// & 监听Song__datas.index变化, 在更新后替换src
watch(
	(): number => Song__datas.index,
	async (newNumber: number): Promise<void> => {
		lasting_add('index', newNumber + '')

		if (newNumber !== -1) {
			const id: string = Song__datas.links[newNumber].id

			const new__src: string = await link_get(id)

			if (audio.src !== new__src) {
				audio.src = new__src
			}

			audio_nature.max = audio.duration

			nextTick((): void => {
				audio__pause_or_play('play')
			})
		} else {
			audio.src = ''
		}
	}
)

export { audio__state, audio__pause_or_play, last_or_next, specify__index }

// ========= dom事件部分 ========= //

// & 当前播放数据
let audio_nature = reactive<{ time: number; max: number; volume: number }>({
	time: 0,
	max: 0,
	volume: 100
})

/**
 * @description: 根据传入值更改进度
 * @param {number} number
 * @return {*}
 */
const audio_time_up = (number: number): void => {
	number = number | 0

	audio_nature.time = number
	audio.currentTime = number

	if (audio__state.value === 'pause') {
		audio__pause_or_play('play')
	}
}

/**
 * @description: 根据传入值更改音量
 * @param {number} number
 * @return {*}
 */
const audio_volume_up = (number: number): void => {
	audio_nature.volume = number
	audio.volume = number / 100
}

/**
 * @description: 播放进度更新
 * @param {*} void
 * @return {*}
 */
const ontimeupdate = (): void => {
	audio_nature.time = audio.currentTime
}

audio.addEventListener('loadeddata', () => {
	audio_nature.max = audio.duration
})

audio.addEventListener(`timeupdate`, ontimeupdate) // & 监听播放进度变化，更新播放进度控件的值。

audio.addEventListener('ended', () => {
	audio_nature.time = 0
	last_or_next()
})

export { audio_nature, audio_time_up, audio_volume_up }
